package com.r2coding.domain.strategy.service.rule.factory;

import com.r2coding.domain.strategy.model.entity.RuleActionEntity;
import com.r2coding.domain.strategy.service.annotation.LogicStrategy;
import com.r2coding.domain.strategy.service.rule.IRuleLogicFilter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.GenericTypeResolver;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author caolx
 * @description 抽奖规则工厂 - 优化版本
 * @date 2025/8/2 13:35
 */
@Slf4j
@Service
public class DefaultLogicFactory {

    private static final Map<String, IRuleLogicFilter<RuleActionEntity.RaffleBeforeEntity>> RAFFLE_BEFORE_FILTER_MAP = new ConcurrentHashMap<>();

    private static final Map<String, IRuleLogicFilter<RuleActionEntity.RaffleCenterEntity>> RAFFLE_CENTER_FILTER_MAP = new ConcurrentHashMap<>();

    // 类型缓存，避免重复反射调用
    private static final Map<Class<?>, Class<?>> TYPE_CACHE = new ConcurrentHashMap<>();

    public DefaultLogicFactory(List<IRuleLogicFilter<?>> logicFilters) {
        log.info("开始初始化规则过滤器工厂，共有 {} 个过滤器", logicFilters.size());

        logicFilters.forEach(this::registerFilter);

        log.info("规则过滤器工厂初始化完成 - 抽奖前过滤器: {}", RAFFLE_BEFORE_FILTER_MAP.size());
    }

    /**
     * 注册过滤器到相应的Map中 - 优化版本
     */
    private void registerFilter(IRuleLogicFilter<?> logicFilter) {
        LogicStrategy annotation = AnnotationUtils.findAnnotation(logicFilter.getClass(), LogicStrategy.class);
        if (annotation == null) {
            log.warn("过滤器 {} 缺少 @LogicStrategy 注解，跳过注册", logicFilter.getClass().getSimpleName());
            return;
        }

        String code = annotation.logicMode().code;
        Class<?> genericType = getGenericType(logicFilter);

        // 使用类型判断直接分发到对应的Map
        if (RuleActionEntity.RaffleBeforeEntity.class.equals(genericType)) {
            addToRaffleBeforeMap(code, logicFilter);
            log.info("注册【抽奖前】过滤器: {} -> {}", code, logicFilter.getClass().getSimpleName());
        } else if (RuleActionEntity.RaffleCenterEntity.class.equals(genericType)) {
            addToRaffleCenterMap(code, logicFilter);
            log.info("注册【抽奖中】过滤器: {} -> {}", code, logicFilter.getClass().getSimpleName());
        }
    }

    /**
     * 安全地添加到【抽奖前】过滤器Map
     */
    @SuppressWarnings("unchecked")
    private void addToRaffleBeforeMap(String code, IRuleLogicFilter<?> logicFilter) {
        RAFFLE_BEFORE_FILTER_MAP.put(code, (IRuleLogicFilter<RuleActionEntity.RaffleBeforeEntity>) logicFilter);
    }

    /**
     * 安全地添加到【抽奖中】过滤器Map
     */
    @SuppressWarnings("unchecked")
    private void addToRaffleCenterMap(String code, IRuleLogicFilter<?> logicFilter) {
        RAFFLE_CENTER_FILTER_MAP.put(code, (IRuleLogicFilter<RuleActionEntity.RaffleCenterEntity>) logicFilter);
    }

    /**
     * 获取【抽奖前】过滤器Map
     */
    public Map<String, IRuleLogicFilter<RuleActionEntity.RaffleBeforeEntity>> getRaffleBeforeFilterMap() {
        return RAFFLE_BEFORE_FILTER_MAP;
    }

    /**
     * 获取【抽奖中】过滤器Map
     */
    public Map<String, IRuleLogicFilter<RuleActionEntity.RaffleCenterEntity>> getRaffleCenterFilterMap() {
        return RAFFLE_CENTER_FILTER_MAP;
    }

    /**
     * 使用Spring GenericTypeResolver优雅地获取泛型类型 - 带缓存优化
     */
    private Class<?> getGenericType(IRuleLogicFilter<?> filter) {
        Class<?> filterClass = filter.getClass();

        // 先从缓存中获取
        return TYPE_CACHE.computeIfAbsent(filterClass, clazz -> {
            Class<?> resolvedType = GenericTypeResolver.resolveTypeArgument(clazz, IRuleLogicFilter.class);
            Class<?> result = resolvedType != null ? resolvedType : RuleActionEntity.RaffleEntity.class;

            log.debug("解析过滤器 {} 的泛型类型: {}", clazz.getSimpleName(), result.getSimpleName());

            return result;
        });
    }

    @Getter
    @AllArgsConstructor
    public enum LogicModel {
        RULE_WEIGHT("rule_weight", RuleType.BEFORE, "【抽奖前规则】根据抽奖权重返回可抽奖范围KEY"),
        RULE_BLACKLIST("rule_blacklist", RuleType.BEFORE, "【抽奖前规则】黑名单规则过滤，命中黑名单则直接返回"),
        RULE_WHITELIST("rule_whitelist", RuleType.BEFORE, "【抽奖前规则】白名单规则过滤，命中白名单则直接返回"),
        RULE_LOCK("rule_lock", RuleType.CENTER, "【抽奖中规则】抽奖n次后，对应奖品可解锁抽奖");

        private final String code;
        private final RuleType type;
        private final String desc;

        /**
         * 判断给定的规则代码是否为抽奖中规则
         *
         * @param code 规则代码
         * @return 如果是抽奖中规则返回true，否则返回false
         */
        public static boolean isCenter(String code) {
            if (code == null || code.trim().isEmpty()) {
                return false;
            }

            // 通过code字段查找对应的LogicModel
            for (LogicModel model : LogicModel.values()) {
                if (model.code.equals(code)) {
                    return model.type.isCenter();
                }
            }

            // 如果找不到对应的规则，返回false
            return false;
        }

        /**
         * 判断给定的规则代码是否为抽奖后规则
         *
         * @param code 规则代码
         * @return 如果是抽奖后规则返回true，否则返回false
         */
        public static boolean isAfter(String code) {
            if (code == null || code.trim().isEmpty()) {
                return false;
            }

            // 通过code字段查找对应的LogicModel
            for (LogicModel model : LogicModel.values()) {
                if (model.code.equals(code)) {
                    return model.type.isAfter();
                }
            }

            // 如果找不到对应的规则，返回false
            return false;
        }

        /**
         * 规则类型枚举
         */
        @Getter
        @AllArgsConstructor
        public enum RuleType {
            BEFORE("before", "抽奖前规则"),
            CENTER("center", "抽奖中规则"),
            AFTER("after", "抽奖后规则");

            private final String code;
            private final String desc;

            /**
             * 判断是否为抽奖中规则
             *
             * @return 如果是抽奖中规则返回true
             */
            public boolean isCenter() {
                return "center".equals(code);
            }

            /**
             * 判断是否为抽奖前规则
             *
             * @return 如果是抽奖前规则返回true
             */
            public boolean isBefore() {
                return "before".equals(code);
            }

            /**
             * 判断是否为抽奖后规则
             *
             * @return 如果是抽奖后规则返回true
             */
            public boolean isAfter() {
                return "after".equals(code);
            }
        }
    }
}
